package jmu.edu.yjc.service.impl.user;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jmu.edu.yjc.Utils.BeanCopyUtil;
import jmu.edu.yjc.Utils.RedisCache;
import jmu.edu.yjc.Utils.SecurityUtil;
import jmu.edu.yjc.constants.SystemConstants;
import jmu.edu.yjc.domain.ResponseResult;
import jmu.edu.yjc.domain.dto.UserDto;
import jmu.edu.yjc.domain.dto.UserRegisterDto;
import jmu.edu.yjc.domain.entity.Role;
import jmu.edu.yjc.domain.entity.Type;
import jmu.edu.yjc.domain.entity.User;
import jmu.edu.yjc.domain.entity.UserRole;
import jmu.edu.yjc.domain.vo.PageVo;
import jmu.edu.yjc.domain.vo.user.UserEditVo;
import jmu.edu.yjc.domain.vo.user.UserInfoVo;
import jmu.edu.yjc.domain.vo.user.UserVo;
import jmu.edu.yjc.enums.AppHttpCodeEnum;
import jmu.edu.yjc.exception.SystemException;
import jmu.edu.yjc.mapper.UserMapper;
import jmu.edu.yjc.service.RoleService;
import jmu.edu.yjc.service.TypeService;
import jmu.edu.yjc.service.UserRoleService;
import jmu.edu.yjc.service.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户表(User)表服务实现类
 *
 * @author makejava
 * @since 2023-01-17 17:06:08
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RoleService roleService;
    @Resource
    private TypeService typeService;
    @Resource
    private RedisCache redisCache;
    @Override
    public ResponseResult userInfo() {
       //获取当前用户id
        Long userId = SecurityUtil.getUserId();
        //根据id查询用户信息
        User user = getById(userId);
        //封装成userInfo
        UserInfoVo vo = BeanCopyUtil.copyBeans(user, UserInfoVo.class);
        return ResponseResult.okResult(vo);
    }

    @Override
    public ResponseResult saveUserInfo(User user) {
        try {
            updateById(user);
            return ResponseResult.okResult();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR);
        }

    }

    @Override
    public ResponseResult userRegister(HttpServletRequest request,UserRegisterDto user) {
        try {
            //判断用户名是否存在
            if(userNameExist(user.getUserName())){
                return ResponseResult.errorResult(AppHttpCodeEnum.USERNAME_EXIST);
            }
            String code = redisCache.getCacheObject("code:" + user.getUserName());
            if(code == null) {
                return ResponseResult.errorResult(-1, "验证码已过期请重新获取");
            }
            if(!user.getCode().equals(code)){
                return ResponseResult.errorResult(AppHttpCodeEnum.CODE_ERROR);
            }
            //对密码进行加密处理
            String encode = passwordEncoder.encode(user.getPassword());
            user.setPassword(encode);
            User beans = BeanCopyUtil.copyBeans(user, User.class);
            //保存用户
            save(beans);
            return ResponseResult.okResult();
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR);
        }
    }

    @Override
    public ResponseResult listUser(Integer pageNum, Integer pageSize, String userName, String phonenumber, String status) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(userName),User::getUserName,userName);
        queryWrapper.like(StringUtils.hasText(phonenumber),User::getPhonenumber,phonenumber);
        queryWrapper.eq(StringUtils.hasText(status),User::getStatus,status);
        queryWrapper.ne(User::getId,SystemConstants.ROOT);
        Page<User> page = new Page<>(pageNum,pageSize);
        page(page,queryWrapper);
        List<User> users = page.getRecords();
        List<UserVo> userVos = BeanCopyUtil.copyBeanList(users, UserVo.class);
        userVos.forEach(vo ->{
            Type type = typeService.getTypeByTypeID(vo.getType());
            vo.setTypeName(type.getTypeName());
        });
        return ResponseResult.okResult(new PageVo(userVos,page.getTotal()));
    }
    @Transactional
    @Override
    public ResponseResult addUser(UserDto userDto) {
        User user = BeanCopyUtil.copyBeans(userDto, User.class);
        //对密码进行加密处理
        String encode = passwordEncoder.encode(user.getPassword());
        user.setPassword(encode);
        save(user);
        userDto.setId(user.getId());
        if(userDto.getRoleIds().size()>0){
            insertUserRole(userDto);
        }
        return ResponseResult.okResult();
    }
    @Override
    public boolean userNameExist(String userName) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName,userName);
        return count(queryWrapper)>0;
    }
    private void insertUserRole(UserDto userDto){
        List<UserRole> userRoles = userDto.getRoleIds().stream()
                .map(roleId -> new UserRole(userDto.getId(), roleId))
                .collect(Collectors.toList());
        userRoleService.saveBatch(userRoles);
    }
    @Override
    public ResponseResult editUser(Long userId) {
        User user = getById(userId);
        UserVo userVo = BeanCopyUtil.copyBeans(user, UserVo.class);
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getStatus, SystemConstants.STATUS_NORMAL);
        List<Role> roles = roleService.list(queryWrapper);
        List<Long> roleIds = userRoleService.selectUserRoleByUserId(userId);
        List<Type> types = typeService.list();
        return ResponseResult.okResult(new UserEditVo(userVo,roleIds,roles,types));
    }
    @Transactional
    @Override
    public ResponseResult doEditUser(UserDto userDto) {
        User user = BeanCopyUtil.copyBeans(userDto, User.class);
        //保存
        updateById(user);
        //删除原有的userRole
        userRoleService.deleteUserRoleByUserId(userDto.getId());
        //插入新的
        insertUserRole(userDto);
        return ResponseResult.okResult();
    }

    @Override
    public List<String> userCountByProvince() {
        return baseMapper.userCountByProvince();
    }

    @Override
    public List<User> getServers() {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getType,SystemConstants.USER_DOCTOR);
        wrapper.eq(User::getDelFlag,SystemConstants.STATUS_NORMAL);
        return list(wrapper);
    }

    @Override
    public User getRobot() {
        LambdaQueryWrapper<User> robot = new LambdaQueryWrapper<>();
        robot.eq(User::getType,SystemConstants.ROBBOT);
        return getOne(robot);
    }

    @Override
    public ResponseResult queryUser(String query) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(query),User::getUserName,query)
                .or()
                .like(StringUtils.hasText(query),User::getNickName,query);
        List<User> users = list(wrapper);
        List<UserVo> userVos = BeanCopyUtil.copyBeanList(users, UserVo.class);
        return ResponseResult.okResult(userVos);
    }

    @Override
    public List<String> getUserAreaList() {
        return baseMapper.userCountByProvince();
    }

    @Override
    public ResponseResult updatePassword(HttpServletRequest request, UserRegisterDto user) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserName, user.getUserName());
        User one = getOne(wrapper);
        if(one == null) {
            return ResponseResult.errorResult(-1,"用户不存在");
        }
        if(!user.getEmail().equals(one.getEmail())) {
            return ResponseResult.errorResult(-1,"所填邮箱与预留邮箱不符");
        }
        String code = redisCache.getCacheObject("code:" + user.getUserName());
        if(code == null) {
            return ResponseResult.errorResult(-1, "验证码已过期请重新获取");
        }
        if(!user.getCode().equals(code)){
            return ResponseResult.errorResult(AppHttpCodeEnum.CODE_ERROR);
        }
        String encode = passwordEncoder.encode(user.getPassword());
        user.setPassword(encode);
        User beans = BeanCopyUtil.copyBeans(user, User.class);
        beans.setId(one.getId());
        updateById(beans);
        return ResponseResult.okResult();
    }
}
